<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <style>
      /* 填写样式 */
      body,
      html {
        padding: 0;
        margin: 0;
        font-size: 14px;
        color: #000000;
      }
      table {
        border-collapse: collapse;
        width: 100%;
        table-layout: fixed;
      }
      thead {
        background: #3d444c;
        color: #ffffff;
      }
      td,
      th {
        border: 1px solid #e1e1e1;
        padding: 0;
        height: 30px;
        line-height: 30px;
        text-align: center;
      }
    </style>
  </head>

  <body>
    <!-- 填写标签 -->
    <table id="jsTrolley">
      <thead>
        <tr>
          <th>名称</th>
          <th>价格</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>产品1</td>
          <td>10.00</td>
          <td><a href="javascript:void(0);">删除</a></td>
        </tr>
        <tr>
          <td>产品2</td>
          <td>30.20</td>
          <td><a href="javascript:void(0);">删除</a></td>
        </tr>
        <tr>
          <td>产品3</td>
          <td>20.50</td>
          <td><a href="javascript:void(0);">删除</a></td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <th>总计</th>
          <td colspan="2">60.70(3件商品)</td>
        </tr>
      </tfoot>
    </table>
    <script type="text/javascript">
      // 填写JavaScript
      /**
       * 一道很常规的应用型题，实现不难，但通过率很低，我也纳闷，
       * wa了几次，后面分析测例才发现，按理全局使用getElementsByTagName获取的DOM会动态变化，\
       * 但测例里面有个直接用innerHTML复原DOM的用法，
       * 这不就完了，全局绑定的元素绑定断开了，函数里拿到的都是空数据能不错嘛，解决方法呢就是随用随筛，不用全局的
       * 一些基础的内容小友相比以及炉火纯青，这里提个容易忽略的点`target.tagName != "A"`这句，
       * A切勿写成小写的，这是硬性的规则！！！
       */
      const calTotalPrice = (goodsListDom) =>
        (document.querySelector("tfoot tr td").innerHTML =
          String(
            Array.from(goodsListDom)
              .reduce((previous, current) => {
                return previous + parseFloat(current.children[1].innerHTML);
              }, 0)
              .toFixed(2)
          ) + `(${goodsListDom.length}件商品)`);

      // 添加商品数据
      const add = (items) => {
        let tbody = document.getElementsByTagName("tbody")[0];
        items.forEach(
          (item) =>
            (tbody.innerHTML += `<tr>
          <td>${item.name}</td>
          <td>${item.price.toFixed(2)}</td>
          <td><a href="javascript:void(0);">删除</a></td>
        </tr>`)
        );
        calTotalPrice(tbody.children);
      };

      //绑定点击事件
      const bind = () => {
        let tbody = document.getElementsByTagName("tbody")[0];
        tbody.onclick = ({ target }) =>
          target.tagName != "A" ? "" : deleteItemEvent(target);
      };

      //删除商品事件
      const deleteItemEvent = (target) => {
        let tbody = document.getElementsByTagName("tbody")[0];
        target.closest("tr").remove();
        calTotalPrice(tbody.children);
      };

      //测例
      function aaa() {
        clear();
        var items = [
          { name: "1", price: 1 },
          { name: "2", price: 2 },
          { name: "3", price: 3 },
        ];
        add(items);
        bind();
        var tbody = document
          .getElementById("jsTrolley")
          .getElementsByTagName("tbody")[0];
        tbody
          .getElementsByTagName("tr")[0]
          .getElementsByTagName("a")[0]
          .click();
        items.shift();
        result = checkSame(items);
        result = result && checkTotal();
        return result;
        function checkSame(items) {
          var table = document.getElementById("jsTrolley");
          var tbody = table.getElementsByTagName("tbody")[0];
          var tr = [].slice.call(tbody.getElementsByTagName("tr"), 0);
          var result = true;
          tr.forEach(function (tr, index) {
            var td = [].slice.call(tr.getElementsByTagName("td"), 0);
            result =
              result &&
              td[0].innerHTML.trim() === items[index].name &&
              td[1].innerHTML.trim() === items[index].price.toFixed(2) &&
              td[2].innerHTML.trim() ===
                '<a href="javascript:void(0);">删除</a>';
          });
          return result;
        }
        function checkTotal() {
          var table = document.getElementById("jsTrolley");
          var tbody = table.getElementsByTagName("tbody")[0];
          var tfoot = table.getElementsByTagName("tfoot")[0];
          var tr = [].slice.call(tbody.getElementsByTagName("tr"), 0);
          var total = 0;
          tr.forEach(function (tr) {
            total += +tr.getElementsByTagName("td")[1].innerHTML.trim();
          });
          var content = tfoot.getElementsByTagName("td")[0].innerHTML.trim();
          var result =
            content === total.toFixed(2) + "(" + tr.length + "件商品)";
          return result;
        }
        function clear() {
          document.body.innerHTML =
            '<table id="jsTrolley"><thead><tr><th>名称</th><th>价格</th><th>操作</th></tr></thead><tbody></tbody><tfoot><tr><th>总计</th><td colspan="2">0(0件商品)</td></tr></tfoot></table>';
        }
      }
      console.log(aaa());
    </script>
  </body>
</html>
